package liming.tool.pool;

import liming.tool.thread.ThreadExecutor;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class PoolEventCenter {
    private static final Set<PoolEventList> poolEventListSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
    private static final ThreadExecutor asyncExecutor = new ThreadExecutor("PoolEventCenter", 1, 0, 0, 10_000, 1.5, 1000);
    // 新增方法：根据名字或对象池获取事件列表
    private static PoolEventList getPoolEventList(String name) {
        for (PoolEventList list : poolEventListSet) {
            if (list.name.equals(name)) return list;
        }
        return null;
    }

    private static PoolEventList getPoolEventList(ObjectsPool<?> pool) {
        for (PoolEventList list : poolEventListSet) {
            if (list.objectPool == pool) return list;
        }
        return null;
    }

    /**
     * 注册数据池
     */
    public static <T> boolean registerEvent(String name, ObjectsPool<T> objectPool) {
        if(objectPool.isEventing() || getPoolEventList(name) != null)
            return false;
        PoolEventList eventList = new PoolEventList(name, objectPool);
        synchronized (poolEventListSet){
            poolEventListSet.add(eventList);
//            objectPool.setPoolEvent((event,pool,value) ->  eventList.run(event,value));
            objectPool.setPoolEvent((event,pool,value) -> {
                if(asyncExecutor.isShutdown()) asyncExecutor.restart();
                asyncExecutor.submit(() -> eventList.run(event,value));
            });
        }

        return true;
    }

    /**
     * 添加事件监听器到指定事件类型
     *
     * @param poolEventInterface 事件处理器
     * @param event 要监听的事件类型
     * @param events 其他要监听的事件类型
     * @return 是否添加成功
     */
    public static <T> boolean addEvent(String name, PoolEventInterface<T> poolEventInterface, PoolEventEnum event, PoolEventEnum... events) {
        PoolEventList eventList = getPoolEventList(name);
        if (eventList == null)
            return false;
        return addEvent(eventList, poolEventInterface, event, events);
    }
    public static <T> boolean addEvent(ObjectsPool<T> objectPool, PoolEventInterface<T> poolEventInterface, PoolEventEnum event, PoolEventEnum... events) {
        PoolEventList eventList = getPoolEventList(objectPool);
        if (eventList == null)
            return false;
        return addEvent(eventList, poolEventInterface, event, events);
    }
    public static <T> boolean addEvent(String name, ObjectsPool<T> objectPool,PoolEventInterface<T> poolEventInterface, PoolEventEnum event, PoolEventEnum... events) {
        PoolEventList eventList1 = getPoolEventList(name);
        PoolEventList eventList2 = getPoolEventList(objectPool);
        if(eventList2 == null || eventList1 != eventList2)
            return false;
        return addEvent(eventList1, poolEventInterface,event, events);
    }
    private static <T> boolean addEvent(PoolEventList eventList, PoolEventInterface<T> poolEventInterface, PoolEventEnum event, PoolEventEnum... events) {
        if(poolEventInterface==null)
            return false;
        eventList.add(event, poolEventInterface);
        for (PoolEventEnum type : events)
            eventList.add(type, poolEventInterface);
        return true;
    }

    /**
     * 从指定事件类型移除事件监听器
     *
     * @param name 注册时使用的名称
     * @param poolEventInterface 要移除的事件处理器
     * @param event 要解绑的事件类型
     * @param events 其他要解绑的事件类型
     * @return 是否移除成功
     */
    public static <T> boolean removeEvent(String name, PoolEventInterface<T> poolEventInterface, PoolEventEnum event, PoolEventEnum... events) {
        PoolEventList eventList = getPoolEventList(name);
        if (eventList == null)
            return false;
        return removeEvent(eventList, poolEventInterface, event, events);
    }
    public static <T> boolean removeEvent(ObjectsPool<T> objectPool, PoolEventInterface<T> poolEventInterface, PoolEventEnum event, PoolEventEnum... events) {
        PoolEventList eventList = getPoolEventList(objectPool);
        if (eventList == null)
            return false;
        return removeEvent(eventList, poolEventInterface, event, events);
    }
    public static <T> boolean removeEvent(String name, ObjectsPool<T> objectPool,PoolEventInterface<T> poolEventInterface, PoolEventEnum event, PoolEventEnum... events) {
        PoolEventList eventList1 = getPoolEventList(name);
        PoolEventList eventList2 = getPoolEventList(objectPool);
        if(eventList2 == null || eventList1 != eventList2)
            return false;
        return removeEvent(eventList1, poolEventInterface,event, events);
    }
    private static <T> boolean removeEvent(PoolEventList eventList, PoolEventInterface<T> poolEventInterface, PoolEventEnum event, PoolEventEnum... events) {
        if(poolEventInterface==null)
            return false;
        eventList.remove(event, poolEventInterface);
        for (PoolEventEnum type : events) {
            eventList.remove(type, poolEventInterface);
        }
        return true;
    }

    /**
     * 注销数据池
     */
    public static <T> boolean unRegisterEvent(String name) {
        PoolEventList eventList = getPoolEventList(name);
        if (eventList == null)
            return false;
        return unRegisterEvent(eventList);
    }
    public static <T> boolean unRegisterEvent(ObjectsPool<T> objectPool) {
        PoolEventList eventList = getPoolEventList(objectPool);
        if (eventList == null)
            return false;
        return unRegisterEvent(eventList);
    }
    public static <T> boolean unRegisterEvent(String name,ObjectsPool<T> objectPool) {
        PoolEventList eventList1 = getPoolEventList(name);
        PoolEventList eventList2 = getPoolEventList(objectPool);
        if(eventList2 == null || eventList1 != eventList2)
            return false;
        return unRegisterEvent(eventList1);
    }
    private static boolean unRegisterEvent(PoolEventList eventList) {
        poolEventListSet.remove(eventList);
        eventList.objectPool.removePoolEvent();
        if(poolEventListSet.isEmpty())
            asyncExecutor.shutdown();
        return true;
    }
    private static class PoolEventList{
        String name;
        ObjectsPool<Object> objectPool;
        Map<PoolEventEnum, Set<PoolEventInterface<Object>>> map;
        <T> PoolEventList(String name, ObjectsPool<T> objectPool){
            this.name=name;
            this.objectPool= (ObjectsPool<Object>) objectPool;
            map=new HashMap<>();
            for (PoolEventEnum value : PoolEventEnum.values())
                map.put(value,new HashSet<>());
        }

        <T> void add(PoolEventEnum event,PoolEventInterface<T> poolEventInterface){
            if(event==null||poolEventInterface==null)return;
            synchronized (this){
                map.get(event).add((PoolEventInterface<Object>) poolEventInterface);
            }
        }

        <T> void remove(PoolEventEnum event,PoolEventInterface<T> poolEventInterface){
            if(event==null||poolEventInterface==null)return;
            synchronized (this){
                map.get(event).remove((PoolEventInterface<Object>)poolEventInterface);
            }
        }

        <T> void run(PoolEventEnum event,T value){
            if(event==null)return;
            map.get(event).forEach((eventInterface)->eventInterface.onEvent(event,objectPool,value));
        }

        @Override
        public int hashCode() {
            return Objects.hash(name, objectPool);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof PoolEventList)) return false;
            PoolEventList that = (PoolEventList) o;
            return Objects.equals(name, that.name) && Objects.equals(objectPool, that.objectPool);
        }
    }
}
